﻿/* dk2Repository - Copyright (C) 2011 Daniel Kuczewski http://www.dk2.de/

 * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using dk2Database.Commands;
using dk2Database.Interfaces;

namespace dk2Database
{
    /// <summary>
    /// Stores and executes multiple commands. 
    /// </summary>
    public class CommandInvoker : ICommandInvoker, IConnectionFactory, IDisposable
    {
        private readonly IConnectionFactory _connectionFactory;
        private readonly List<ICommand> _cmds;
        private readonly bool _abortOnError;

        private IConnection _con;

        public CommandInvoker() : this(true, Databases.Default) { }

        public CommandInvoker(bool abortOnError) : this(abortOnError, Databases.Default){ }

        public CommandInvoker(IConnectionFactory connectionFactory) : this(true, connectionFactory) { }

        public CommandInvoker(bool abortOnError, IConnectionFactory connectionFactory)
        {
            _abortOnError = abortOnError;
            _connectionFactory = connectionFactory;
            _cmds = new List<ICommand>();
           
        }

        public void AddCommand(ICommand cmd)
        {
            _cmds.Add(cmd);
        }

        public void AddCommands(IEnumerable<ICommand> cmds)
        {
            _cmds.AddRange(cmds);
        }

        public void Execute()
        {
            using (_con = _connectionFactory.CreateConnection())
            {
                foreach (var cmd in _cmds)
                {
                    cmd.ConnectionFactory = this;

                    try
                    {
                        cmd.Execute();
                    }
                    catch (CommandException)
                    {
                        if (_abortOnError)    
                            throw;
                    }
                }
            }
        }

        public IConnection CreateConnection()
        {
            return new MultiUseConnection(_con.Connection);
        }

        public void Dispose()
        {
            _cmds.Clear();
        }
    }
}
